﻿using System;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Build.Framework;

namespace NotifyPropertyWeaverVsPackage
{
    public class ProjectReader
    {
        string projectFile;
        public string DependenciesDirectory { set; get; }
        public string ToolsDirectory { set; get; }
        public string TargetPath { set; get; }
        public string EventInvokerName { set; get; }
        public MessageImportance? MessageImportance { get; set; }
        public bool? CheckForEquality { set; get; }
        public bool? TryToWeaveAllTypes { set; get; }

        public ProjectReader(string projectFile)
        {
            this.projectFile = projectFile;
            SetWeavingProps();
            DependenciesDirectory = GetDependenciesDirectory(projectFile);
            ToolsDirectory = GetToolsDirectory(projectFile);
        }

        public static string GetDependenciesDirectory(string projectFile)
        {
            var xDocument = XDocument.Load(projectFile);
            var elements =
                from el in xDocument.BuildDescendants("Reference")
                where ((string)el.Attribute("Include")).StartsWith("NotifyPropertyWeaver")
                select el;
            var firstOrDefault = elements.FirstOrDefault();
            if (firstOrDefault != null)
            {
                var value = firstOrDefault.Value;
                return value.Substring(0, value.IndexOf("NotifyPropertyWeaver.dll"));
            }

            return null;
        }

        public static string GetToolsDirectory(string projectFile)
        {
            var xDocument = XDocument.Load(projectFile);
            var elements =
                from el in xDocument.BuildDescendants("UsingTask")
                where (string)el.Attribute("TaskName") == "NotifyPropertyWeaverMsBuildTask.WeavingTask"
                select el.Attribute("AssemblyFile");
            var firstOrDefault = elements.FirstOrDefault();
            if (firstOrDefault != null)
            {
                var value = firstOrDefault.Value;
                return value.Substring(0, value.IndexOf("NotifyPropertyWeaverMsBuildTask.dll"));
            }
            return null;
        }
        void SetWeavingProps()
        {
            var xDocument = XDocument.Load(projectFile);
            var children =
                from target in xDocument.BuildDescendants("Target")
                let targetName = (string) target.Attribute("Name")
                where string.Equals(targetName, "AfterCompile", StringComparison.InvariantCultureIgnoreCase)

                from weavingTask in target.BuildDescendants("NotifyPropertyWeaverMsBuildTask.WeavingTask")
                select new
                           {
                               TargetPath = (string) weavingTask.Attribute("TargetPath"),
                               EventInvokerName = (string) weavingTask.Attribute("EventInvokerName"),
                               CheckForEquality = ToBool(weavingTask.Attribute("CheckForEquality")),
                               TryToWeaveAllTypes = ToBool(weavingTask.Attribute("TryToWeaveAllTypes")),
                               MessageImportance = ConvertToEnum((string) weavingTask.Attribute("MessageImportance")),
                           };

            var first = children.FirstOrDefault();
            if (first == null)
            {
                return;
            }
            TryToWeaveAllTypes = first.TryToWeaveAllTypes;
            CheckForEquality = first.CheckForEquality;
            EventInvokerName = first.EventInvokerName;
            TargetPath = first.TargetPath;
            MessageImportance = first.MessageImportance;
        }
        public static bool? ToBool(XAttribute attribute)
        {
            if (attribute == null)
            {
                return null;
            }
            return bool.Parse(attribute.Value);
        }

        static MessageImportance? ConvertToEnum(string messageImportance)
        {
            if (!string.IsNullOrWhiteSpace(messageImportance))
            {
                MessageImportance messageImportanceEnum;
                if (Enum.TryParse(messageImportance, out messageImportanceEnum))
                {
                    return messageImportanceEnum;
                }
            }
            return null;
        }
    }
}